#ifndef __MY_SERVICE__
#define __MY_SERVICE__
#include "data.hpp"
#include "httplib.h"

extern cloud::DataManager *_data;

namespace cloud
{
    class Service
    {
    public:
        int _server_port;
        std::string _server_ip;
        std::string _download_prefix;
        httplib::Server _server;

    private:
        static void Upload(const httplib::Request &req, httplib::Response &rsp)
        {
            // 判断有没有上传的文件区域
            auto ret = req.has_trailer("file");
            if (ret == false) {
                rsp.status = 400;
                return;
            }
            const auto &file = req.get_trailer_value("file");
            std::string back_dir = Config::GetInstance()->GetBackDir();
            std::string realpath = back_dir + FileUtil(file).FileName();
            FileUtil fu(realpath);
            // 保存上传的文件内容（直接使用请求体作为文件内容）
            if (fu.SetContent(req.body) == false) {
                rsp.status = 500;
                return;
            }
            BackupInfo info;
            info.NewBackupInfo(realpath); // 组织备份的文件信息
            _data->Insert(info);          // 向数据管理模块添加备份的文件信息
            rsp.status = 200;
            return;
        }

        static std::string TimetoStr(time_t t)
        {
            std::string tmp = std::ctime(&t);
            // 移除换行符
            size_t pos = tmp.find('\n');
            if (pos != std::string::npos) {
                tmp.erase(pos);
            }
            return tmp;
        }

        static void ListShow(const httplib::Request &req, httplib::Response &rsp)
        {
            // 1.获取所用的文件备份信息
            std::vector<BackupInfo> arry;
            _data->GetAll(&arry);
            // 2.根据所有备份信息，组织html文件数据
            std::stringstream ss;
            ss << "<html><head><title>Download</title></head>";
            ss << "<body><h1>Download</h1><table>";
            for (auto &a : arry)
            {
                ss << "<tr>";
                std::string filename = FileUtil(a.real_path).FileName();
                ss << "<td><a href='" << a.url << "'>" << filename << "</a></td>";
                ss << "<td align='right'>" << TimetoStr(a.mtime) << "</td>";
                ss << "<td align='right'>" << a.fsize / 1024 << "k</td>";
                ss << "</tr>";
            }
            ss << "</table></body></html>";
            rsp.body = ss.str();
            rsp.set_header("Content-Type", "text/html");
            rsp.status = 200;
            return;
        }

        static std::string GetETag(const BackupInfo &info)
        {
            // etg : filename-fsize-mtime
            FileUtil fu(info.real_path);
            std::string etag = fu.FileName();
            etag += "-";
            etag += std::to_string(info.fsize);
            etag += "-";
            etag += std::to_string(info.mtime);
            return etag;
        }

        static void Download(const httplib::Request &req, httplib::Response &rsp)
        {
            // 1.获取客户端请求的资源路径path req.path
            // 2.根据资源路径，获取文件备份信息
            BackupInfo info;
            if (_data->GetOneByURL(req.path, &info) == false) {
                rsp.status = 404;
                return;
            }
            // 3.判断文件是否压缩，如果压缩，要先解压缩
            if (info.pack_flag == true)
            {
                FileUtil fu(info.pack_path);
                fu.UnCompress(info.real_path); // 将文件解压到备份目录下
                // 4.删除压缩包，修改备份信息（已经没有被压缩）
                fu.Remove();
                info.pack_flag = false;
                _data->Update(info);
            }

            FileUtil fu(info.real_path);
            // 检查文件是否存在
            if (!fu.Exists()) {
                rsp.status = 404;
                return;
            }

            // 设置通用头部
            rsp.set_header("Accept-Ranges", "bytes");
            rsp.set_header("ETag", GetETag(info));
            rsp.set_header("Content-Type", "application/octet-stream");
            
            // 处理Range请求
            if (req.has_header("Range")) {
                std::string range = req.get_header_value("Range");
                // 解析Range头，格式: bytes=start-end
                size_t pos = range.find("=");
                if (pos != std::string::npos) {
                    range = range.substr(pos + 1);
                    pos = range.find("-");
                    if (pos != std::string::npos) {
                        std::string start_str = range.substr(0, pos);
                        std::string end_str = range.substr(pos + 1);
                        size_t start = std::stoull(start_str);
                        size_t end = info.fsize - 1;
                        if (!end_str.empty()) {
                            end = std::stoull(end_str);
                        }
                        
                        // 确保请求的范围有效
                        if (start <= end && end < info.fsize) {
                            size_t len = end - start + 1;
                            if (fu.GetPosLen(&rsp.body, start, len)) {
                                rsp.status = 206; // Partial Content
                                std::string content_range = "bytes " + std::to_string(start) + "-" + 
                                                          std::to_string(end) + "/" + std::to_string(info.fsize);
                                rsp.set_header("Content-Range", content_range);
                                rsp.set_header("Content-Length", std::to_string(len));
                                return;
                            }
                        }
                    }
                }
            }
            
            // 完整下载请求
            if (fu.GetContent(&rsp.body)) {
                rsp.status = 200;
                rsp.set_header("Content-Length", std::to_string(rsp.body.size()));
            } else {
                rsp.status = 500;
            }
        }

    public:
        Service()
        {
            Config *config = Config::GetInstance();
            _server_port = config->GetServerPort();
            _server_ip = config->GetServerIp();
            _download_prefix = config->GetDownloadPrefix();
        }

        bool RunModule()
        {
            _server.Post("/upload", Upload);
            _server.Get("./listshow", ListShow);
            _server.Get("/", ListShow);
            std::string download_url = _download_prefix + "(.*)";
            _server.Get(download_url, Download);
            _server.listen(_server_ip.c_str(), _server_port);
            return true;
        }
    };
}

#endif